package com.netty.client;

import com.common.protobuf.MessageModule;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.springframework.stereotype.Component;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @author 顾志杰
 * @date 2021/3/12-10:01
 */
@Component
public class Client {

    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);

    private EventLoopGroup group = new NioEventLoopGroup(2);

    public static final String HOST = "127.0.0.1";
    public static final int PORT = 8765;

    private Channel channel;

    public Client() throws Exception{
        this.connect(HOST,PORT);
    }

    public void connect(String host,int port) throws Exception{
        // 配置客户端NIO现场组
        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addLast(new ProtobufVarint32FrameDecoder());
                            ch.pipeline().addLast(new ProtobufDecoder(MessageModule.Message.getDefaultInstance()));
                            ch.pipeline().addLast(new ProtobufVarint32LengthFieldPrepender());
                            ch.pipeline().addLast(new ProtobufEncoder());
                            ch.pipeline().addLast(new ClientHandler());
                        }
                    });
            // 发起异步连接操作
            ChannelFuture future = b.connect(host,port).sync();
            this.channel = future.channel();
            System.out.println("Client Start.. ");
            this.channel.closeFuture().sync();
        }finally {
            // 所有资源释放完成之后 清空资源 再次发起重连操作
            executor.execute(() -> {
                try {
                    TimeUnit.SECONDS.sleep(1);
                    try {
                        // 发起重新连接
                        connect(host,port);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
            });
        }
    }
}
